import React from 'react'
// import { Form, FormItem } from '@antd/form/form'
// ===================================================================== antd
import { DownOutlined, UpOutlined  } from '@ant-design/icons'
// ===================================================================== global declare
const { $fn, $Lazy } = window
// ===================================================================== Lazy
const Form 				= $Lazy.hook(()=>import('@antd/form/layout/form'))
const FormItem 			= $Lazy.load(()=>import('@antd/form/layout/item'))
const Input 			= $Lazy.load(()=>import('@antd/form/input'))
const Select 			= $Lazy.load(()=>import('@antd/form/select'))
const SelectTable 		= $Lazy.load(()=>import('@antd/form/select-table'))
const TreeSelect 		= $Lazy.load(()=>import('@antd/form/treeSelect'))
const DatePicker 		= $Lazy.load(()=>import('@antd/form/datePicker'))
const TimePicker 		= $Lazy.load(()=>import('@antd/form/timePicker'))
const Checkbox 			= $Lazy.load(()=>import('@antd/form/checkbox'))
const CheckboxGroup 	= $Lazy.load(()=>import('@antd/form/checkboxGroup'))
const Upload 			= $Lazy.hook(()=>import('@antd/upload'))
const Radio 			= $Lazy.load(()=>import('@antd/form/radio'))
// const Cascader 			= $Lazy.load(()=>import('@antd/form/cascader'))
const Address 			= $Lazy.state(()=>import('@antd/form/address'))
const Switch 			= $Lazy.load(()=>import('@antd/form/switch'))
const SelectInput 		= $Lazy.load(()=>import('@antd/form/select-input'))
const InputRange 		= $Lazy.load(()=>import('@antd/form/input-range'))
const ConversionSelect 	= $Lazy.load(()=>import('@antd/form/conversion-select'))
const Button 			= $Lazy.load(()=>import('@antd/button'))
// const BtnGroup 			= $Lazy.load(()=>import('#tp/btn-group'))
const Title 			= $Lazy.load(()=>import('#tp/title/title-small'))
// =====================================================================
const size = 'middle'
const bordered = false

const FormComponent = ({ data, onChange, width, mb, readOnly, formRef, disabled, noholder, full, half, bind, itemClassName, loading, form, customHide }) => (
	<>
		{
			$fn.hasArray(data) &&  data.map((v,i)=>{
				if(!$fn.hasObject(v)) return null;
				let { type, value, label, name, names, format } = v
				const _disabled = loading || ($fn.isValid(v.disabled) ? v.disabled : disabled)
				// 配置 Item 的宽度
				let itemWidth = 'auto'
				const _width = v.width ? v.width : width
				const _full = v.full ? v.full : full
				const _half = v.half ? v.half : half
				const _itemWidth = v.itemWidth ? v.itemWidth : _width
				
				if(_full){ itemWidth = '100%' }
				else if(_half){ itemWidth = '50%' }
				else if(_itemWidth){ itemWidth = _itemWidth}
				// 可读
				const _readOnly = $fn.isValid(v.readOnly) ?  v.readOnly : readOnly
				// 表单元素改变时监听函数
				const onChanged = option => {
					onChange?.(option)
					v.onChange?.({...option, ref:formRef, form:'formData', data, formData:data})
					v.onValue?.({...option, ref:formRef, form:'formData', data, formData:data})
					if(bind){ 
						v.value = option.value 
					}else{
						if(v.bind){
							v.value = option.value
						}
					}
				}
				// 配置显示表单元素
				let children = null
				if(type === 'select'){	// 下拉框
					children = <Select
						form		= { form }
						name		= { name }
						size		= { size }
						bordered	= { bordered }
						loading 	= { v.loading }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						p			= {v.p ? v.p : '请选择' + label}
						// private
						data		= { v.data } 
						nameStr		= { v.nameStr } 
						idStr		= { v.idStr }
						mode		= { v.mode }
						count		= { v.count }
						auto 
						btn			= { v.btn }
						afterSuffix = { v.afterSuffix }
						icon 		= { v.icon }
						outer
						onChanged	= { option => onChanged.call(null, option)}
						isKeydown	= { v.isKeydown }
						copy 		= { v.copy }
					/> 
				}else if(type === 'select-table'){	// 下拉框
					children = <SelectTable
						name		= { name }
						size		= { size }
						bordered	= { bordered }
						loading 	= { v.loading }
						disabled	= { _disabled }
						outer
						readOnly	= { _readOnly }
						p			= {v.p ? v.p : '请选择' + label}
						// private
						data		= { v.data } 
						idStr		= { v.idStr }
						cols 		= { v.cols }
						isKeydown	= { v.isKeydown }
						onChanged	= { option => onChanged.call(null, option)}
					/> 
				}else if(type === 'treeSelect'){	// 下拉框
					children = <TreeSelect
						name		= { name }
						size		= { size }
						bordered	= { bordered }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						p			= {'请选择' + label}
						// private
						filterName	= { v.filterName }
						data		= { v.data } 
						nameStr		= { v.nameStr } 
						idStr		= { v.idStr }  
						auto 
						onChanged	= { option => onChanged.call(null, option)}
						checkable	={ v.checkable }
						multiple	={ v.multiple }
					/> 
				}else if(type === 'date-range'){	// 日期范围
					children = <DatePicker 
						name		= { v.names }
						size		= { size }
						bordered	= { bordered }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						// private
						range 
						showTime
						format		= { format }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'date-time'){		// 日期
					children = <DatePicker 
						name		= { name }
						size		= { size } 
						bordered	= { bordered }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						before		= { v.before }
						after		= { v.after }
						format		= { v.format }
						defaultPickerValue = { v.defaultPickerValue }
						showTimeStart = { v.showTimeStart ?? false }
						showTimeEnd = { v.showTimeEnd ?? false }
						// private
						showTime
						outer
						onChanged	= { option => onChanged.call(null, option) }
                        picker      = { v.picker }
						submit	= { v.submit }
						showToday	= { v.showToday }
					/>
				}else if(type === 'time'){		// 时间
					children = <TimePicker 
						name		= { name }
						size		= { size } 
						bordered	= { bordered }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						before		= { v.before }
						after		= { v.after }
						p			= { v.p ? v.p : '请选择' + label}
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'checkbox') {		// 复选框
					children = <Checkbox 
						isNumber
						name		= { name }
						label 		= { v.tag ? v.tag : (v.after ? v.label : null) }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						mode		= { v.mode }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/> 
				}else if(type === 'switch') {		// 开关
					children = <Switch 
						name		= { name }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/> 
				}else if(type === 'checkboxGroup') {		// 复选框
					children = <CheckboxGroup 
						name		= { name }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						nameStr		= { v.nameStr }
						idStr		= { v.idStr }  
						data 		= { v.data }
						onChecked 	= { v.onChecked }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/> 
				}else if(type === 'radio'){		// 单选框
					children = <Radio
						name		= { name }
						size		= { v.size ?? size }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						nameStr		= { v.nameStr }
						idStr		= { v.idStr }
						dir			= { v.dir }
						// private
						data		= { v.data } 
						mode		= { v.mode }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'upload'){	// 上传
					children = <Upload
						name 		= { name }
						param		= { v.param }
						query 		= { v.query }
						modular		= { v.modular }
						mode 		= { v.mode }
						multiple	= { v.multiple }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						code		= { v.code }
						api 		= { v.api }
						outer
						{...v}
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if( type === 'cascader'){
					// children = <Cascader
					// 	name		= { name }
					// 	size		= { size }
					// 	bordered	= { bordered }
					// 	loading 	= { v.loading }
					// 	disabled	= { _disabled }
					// 	readOnly	= { _readOnly }
					// 	p			= {v.p ? v.p : '请选择' + label}
					// 	// private
					// 	data		= { v.data }
					// 	outer
					// 	onChanged	= { option => onChanged.call(null, option)}
					// /> 
				}else if( type === 'address'){
					children = <Address
						name		= { name }
						size		= { size }
						bordered	= { bordered }
						loading 	= { v.loading }
						disabled	= { _disabled }
						readOnly	= { _readOnly }
						p			= {v.p ? v.p : '请选择' + label}
						// private
						data		= { v.data }
						onChanged	= { option => onChanged.call(null, option)}
						onRef 		= { v.onRef }
					/> 
				}else if(type === 'textarea'){	// 上传
					children = <Input
						name		= { name }
						size		= { size }
						bordered 	= { bordered } 
						disabled	= { _disabled } 
						readOnly	= { _readOnly } 
						p			= { noholder ? '' : (v.p ?  v.p : '请输入' + label) }
						// private
						mode		= 'textarea'
						rows 		= { v.rows }
						outer
						btn			= { v.btn }
						afterText	= { v.afterText }
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'select-input'){	// 条件选择
					children = <SelectInput
						name		= { names }
						size		= { size }
						bordered 	= { bordered } 
						disabled	= { _disabled } 
						readOnly	= { _readOnly } 
						ps			= { noholder ? null : [v.label, v.label] }
						required	= { v.required }
						data		= { v.data }
						idStr		= { v.idStr }
						nameStr		= { v.nameStr }
						label 		= { v.label }
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'range'){	// 范围输入
					children = <InputRange
						name		= { names }
						size		= { size }
						bordered 	= { bordered } 
						disabled	= { _disabled } 
						readOnly	= { _readOnly }
						required	= { v.required }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'conversion'){	// 范围输入
					children = <ConversionSelect
						value		= { v.value }
						name		= { names }
						size		= { size }
						bordered 	= { bordered } 
						disabled	= { _disabled } 
						readOnly	= { _readOnly }
						required	= { v.required }
						outer
						onChanged	= { option => onChanged.call(null, option) }
					/>
				}else if(type === 'button'){	// 按钮
					children = <Button size='middle' label={v.label} onClick={v.onClick} disabled={_disabled} />
					label = ' '
					v.colon = false
				}else if(type === 'cpt'){
					const C = v.component
					children = typeof C === 'function' ? <C /> : C
				}else{		// 输入框
					children = <Input
						name		= { name }
						size		= { size }
						bordered 	= { bordered } 
						value		= { value }
						disabled	= { _disabled } 
						readOnly	= { _readOnly } 
						p			= { noholder ? '' : (v.p ?  v.p : '请输入' + label) }
						mode 		= { v.type }
						onClick		= { v.onClick }
						onKeyup		= { v.onKeyup }
						btn			= { v.btn }
						suffix		= { v.suffix }
						afterSuffix = { v.afterSuffix }
						afterText	= { v.afterText }
						onEnter 	= { v.onEnter }
						outer
						max			= { v.max }
						minValue	= { v.minValue }
						autoFocus	= { v.autoFocus }
						className	= { v.className }
						onChanged	= { option => onChanged.call(null, option) }
						onBlur 		= { v.onBlur }
					/>
				}
				const isSelect = ['select','date-range','checkbox','radio'].includes(v.type)
				return (
					<React.Fragment key={i}>
						{/* v.title && <div className='w xmlr f12 h40 bbor1 mb10 fxmj'><div className='b'>{v.title}</div><BtnGroup controls={v.titleControls} /></div> */}
						{ v.title && <Title title={v.title}  controls={v.titleControls} className='w bbor1 mb10' /> }
						{ v.br && <div className='w'></div> }
						{/* 病人基本信息 增加5个自定义字段 2021-10-15  --马婷 */}
						{v.custom && <div className='pb10 fxmc w' >
							<span className='ex h1px'></span>
							<span className='f13 c0 cp plr10' onClick={ v.onClick }>
								{ !customHide ? <>收起 <UpOutlined dashed='true' /></> : <>自定义属性 <DownOutlined dashed='true' /></> }
							</span>
							<span className='ex h1px'></span>
						</div>}
						{
							v.type !== 'cpt' ? (
								<>
									{
										!v.hide  && <FormItem
											className 	= {`
												${ type ? 'jzer-' + type + '-item' : '' }
												${v.labelAfter ? 'no-label' : ''}
												${label ? '' : 'no-label'}
												${v.itemClassName || ''} 
												${type==='date-time'?'date-time-picker':''} 
												${itemClassName ? (type==='textarea' ? itemClassName + '-textarea' : itemClassName) : '' }
												${ type==='textarea' ? 'textarea-item' : 'com-item'}
												${$fn.hasObject(v.btn) ? 'item-has-btn' : ''}
												${v.tagWidth ? v.tagWidth : (v.tag ? 't120' : '')}
												${v.type==='textarea' || v.type==='upload' || v.type==='checkboxGroup' || v.count===null ? 'auto-height' : 'fixed-height' }
												${v.type==='textarea' ? 'break-text' : '' }
												${v.readOnly || readOnly ? 'read-only' : ''}
												${v.disabled ? 'item-disabled' : ''}
												${_disabled ? 'form-disabled' : ''}
											`}
											style		= { v.style }
											label		= { label ? label : null } 
											name		= { names&&name ? name : ( names ? [] : name )} 
											width		= { itemWidth } 
											mb			= { $fn.isNumber(v.mb) ? v.mb : mb }
											ml			= { v.ml }
											colon		= { v.label === ' ' || !v.label ? false : v.colon }
											rules		= { [
												{ required: !v.disabled && v.required, message:  isSelect  ? '请选择' + label : '请输入' + label }, 
												...(v.rules||[]) 
											] }
										>	
											{children}
										</FormItem>
									}
								</>
							) : children
						}
					</React.Fragment>
				)
			})
		}
	</>
)

const SubmitForm = ({ 
	children, data, onChange, onSubmit, onClose, init, btnSize='middle', okText='确认', full, half, isModal, itemClassName,
	dir='x', hideButton, width, className, contentClassName, mb=20, readOnly, disabled, noholder, scroll, loading,noEsc,
	bind, labelWidth = 'w60', enter = true, name, style, formRef, onOkClick, customHide
}) => {
	const [ form, setForm ] = React.useState()
	const _init = React.useCallback( v => {
		setForm(v)
		init && init(v, data)
	},[init, data])
	return (
		<Form dir={dir} style={style} onSubmit={onSubmit} name={name} init={_init} className={` ${labelWidth ? labelWidth : ''} submit-form small-form fv ex ${className||''}`}>
			<div className='ex rel'>
				<div className={` ${contentClassName||''} ${scroll?'abs_full oys scrollbar':''}`}>
					<div className={dir === 'x' ? 'fxw' : ''}>
						<FormComponent
							formRef			= { formRef }
							data			= { data } 
							full			= { full } 
							half			= { half } 
							width			= { width } 
							mb				= { mb } 
							readOnly		= { readOnly } 
							disabled		= { disabled } 
							noholder		= { noholder } 
							onChange		= { onChange }
							bind			= { bind }
							loading 		= { loading }
							itemClassName 	= { itemClassName }
							form			= { form }
							customHide		={ customHide }
						/>
						{children}
					</div>
				</div>
			</div>
			{ !hideButton && (
				<div className={`fxmc tbor1 ptb10`}>
					{
						!noEsc && <Button loading={loading} label='返回' ghost className='mr15' size={btnSize} width={btnSize === 'large' ? 120 : 90} onClick={onClose} />
					}
					<Button loading={loading} label={okText}  code={enter?'Enter':null} size={btnSize} width={btnSize === 'large' ? 120 : 90} 
						onClick = {()=>{
							onOkClick ? onOkClick(formRef) : formRef.submit()
						}}
					/>
				</div>
			)}
		</Form>
	)
}

class Index extends React.Component {
    state = {
		
    }
	
	// 初始化并设置默认值
	init = form => {
		const { value, onForm, data } = this.props
		this.form = form
		// 如果有默认值，才设置默认值
		
		if(value){ 
			this.setValue(value)
		}
		onForm && onForm(this, form)
		// 检测是否有默认值 value
		if($fn.hasArray(data)){
			const values = data.filter(v => $fn.isValid(v))
			if($fn.hasArray(values)){
				this.setDataValue(values)
			}
		}
	}
	// 将表单元素列表数据上的值绑定到表单
	setDataValue = data => {
		data.forEach(m=>{
			if( $fn.hasObject(m) && $fn.isValid(m.value)){
				this.form.setFieldsValue({ [m.name] : m.value })
			}
		})
	}
	// 自定义设置默认值
	setBindValue = (data, values) => {
		for(let i in values){
			let { name, value } = values[i]
			data.forEach(p=>{
				if($fn.hasObject(p) && name === p.name){
					p.value = value
				}
			})
		}
	}
	// 设置默认值
	setValue = value => {
		const { data } = this.props
		if($fn.hasObject(value)){
			let _value = {}
			data.forEach(v => {
				if($fn.hasObject(v)){
					const name = v.name
					if(value[name] !== undefined){
						_value[name] = value[name]
					}
				}
			})
			this.form.setFieldsValue(_value)
		}else if($fn.hasArray(value)){
			this.setDataValue(value)
		}
	}
	// 提交表单
	submit = () => this.form.submit()
	// 重置表单
	reset = names => this.form.resetFields(names)
	// 获取 name 字段的值
	getName = name => this.form.getFieldValue(name)
	// 获取 name 字段的值
	getValue = names => this.form.getFieldsValue(names)
	
	render(){
		const { children, dir, data } = this.props
		if($fn.hasArray(data)){
			data.forEach(v=>{
				if( $fn.hasObject(v) && v.names){
					v.names.forEach(p=> data.push({ name:p, hide:true, value:v.value }))
				}
			})
		}
		return (
			<SubmitForm
				{...this.props}
				formRef		= { this }
				data 		= { data }
				init		= { this.init }
				layout		= { dir === 'y' ? 'vertical' : 'horizontal'}
			> {children} </SubmitForm>
		)
	}
}

export default Index